package org.lqk.file.transfer.client.processor;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.CRC32;

import org.apache.commons.io.IOUtils;
import org.lqk.file.transfer.Constant;
import org.lqk.file.transfer.client.framework.AbstractFileResponseProcessor;
import org.lqk.file.transfer.netty.RequestFuture;
import org.lqk.file.transfer.protocol.*;

import io.netty.channel.ChannelHandlerContext;

/*
 * 
 */

public class FileTaskResponseProcessor extends AbstractFileResponseProcessor {

	public FileTaskResponseProcessor(ConcurrentHashMap<Integer, RequestFuture> requestTable, int cmdCode) {
		super(requestTable, cmdCode);
	}

	@Override
	public boolean process(ChannelHandlerContext ctx, RemotingCommand command) throws IOException {
		RequestFuture requestFuture = requestTable.get(command.getOpaque());

		if (command.isFlag()) {
			RemotingCommand requestCommand = requestFuture.getRequestCommand();
			FileTaskRequest fileTaskRequest = (FileTaskRequest) requestCommand.getBody();
			String filePath = fileTaskRequest.getFilePath();
			sendSegments(ctx,new File(filePath),command.getOpaque());
			return false;
		}
		// 中断执行流程
		return true;
	}

	private void sendSegments(ChannelHandlerContext ctx,File file, int opaque) {
		boolean done = false;
		RandomAccessFile raf = null;
		FileChannel channel = null;
		try {
			int blockSize = Constant.BLOCK_SIZE;
			raf = new RandomAccessFile(file, "r");
			channel = raf.getChannel();
			long position = 0;
			ByteBuffer buffer = ByteBuffer.allocate(blockSize);
			int size = blockSize;
			CRC32 crc32 = new CRC32();
			byte[] b = new byte[size];
			while (!done) {
				channel.position(position);
				channel.read(buffer);
				FileSegmentRequest segmentRequest = new FileSegmentRequest();
				if (position + blockSize >= file.length()) {
					size = (int) (file.length() - position);
					done = true;
				}
				buffer.flip();
				buffer.get(b, 0, size);
				segmentRequest.setContent(b);
				crc32.update(b);
				segmentRequest.setCrc32(crc32.getValue());
				crc32.reset();
				segmentRequest.setBlockSize(size);
				segmentRequest.setFileName(file.getName());
				segmentRequest.setPosition(position);
				RemotingCommand command1 = new RemotingCommand(CmdCode.File_Segment.getCode(), RpcType.File_Request.getCode(), false,opaque);
				command1.setOpaque(opaque);
				command1.setBody(segmentRequest);

				ctx.writeAndFlush(command1);

				position += size;
				buffer.clear();
				
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(channel);
			IOUtils.closeQuietly(raf);
		}
	}

}
